package cc.catface.base.net.core;

import android.annotation.SuppressLint;
import android.text.TextUtils;
import android.util.ArrayMap;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

/** 拦截器:添加公共参数;打印日志 */
public class BizInterceptor implements Interceptor {

    @NonNull
    @Override
    public Response intercept(Chain chain) throws IOException {
        long n1 = System.nanoTime();
        Request request = chain.request();
        Request.Builder builder = request.newBuilder();
        setNormalRequestHeaders(builder);//添加请求头

        //请求参数
        URL url = new URL(request.url().toString());
        String queryString = url.getQuery();//请求query(&拼在url后面所以会被url编码)
        String queryStringDecode = TextUtils.isEmpty(queryString) ? "" : URLDecoder.decode(queryString, "UTF-8");//URL解码后的请求query
        String requestBody = getRequestBodyStr(request.body());//请求body(json)

        //diy添加验签头
        //String signatureStr = RequestUtils.getHmacString(request.method(), requestParamsForKey, urlPath, queryStringDecode, randomUUID, hmacTime);
        //builder.addHeader("Signature", signatureStr);

        //发起真正请求
        Response response = chain.proceed(builder.build());
        String responseBody = getResponseBody(response);//响应数据

        RetrofitHelper.d(String.format("开始本次请求→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→" +
                        "\n%s %s %s %sms" +//请求方法 url 响应码 耗时
                        "\n响应body:%s" +//响应数据
                        "\n请求body:%s" +//请求body(json)
                        "\n请求query(source):%s" +//请求query(source)
                        "\n请求query(decode):%s" +//请求query(decode)
                        "\n请求头:%s" +//请求头
                        "响应头:%s" +//响应头
                        "结束本次请求←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←",
                request.method(), request.url(), response.code(), TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - n1),
                responseBody, requestBody, queryString, queryStringDecode, builder.build().headers().toString(), response.headers().toString()));
        return response;
    }

    /*请求body转字符串*/
    public String getRequestBodyStr(RequestBody requestBody) throws IOException {
        if (requestBody == null) return "";
        Buffer buffer = new Buffer();
        requestBody.writeTo(buffer);
        return buffer.readUtf8();
    }

    /*服务器响应的body*/
    static String getResponseBody(Response response) {
        String result = "";
        try {
            ResponseBody responseBody = response.body();
            if (responseBody == null) return null;
            long contentLength = responseBody.contentLength();
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE);
            Buffer buffer = source.buffer();
            Charset charset = StandardCharsets.UTF_8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(StandardCharsets.UTF_8);
            }
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64 ? buffer.size() : 64;
            buffer.copyTo(prefix, 0, byteCount);
            for (int i = 0; i < 16; i++) {
                if (prefix.exhausted()) break;
                int codePoint = prefix.readUtf8CodePoint();
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) return null;
            }
            if (contentLength != 0 && null != charset) {
                result = buffer.clone().readString(charset);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }


    /** 设置公共请求头 */
    @SuppressLint("NewApi")
    private void setNormalRequestHeaders(Request.Builder builder) {
        ArrayMap<String, String> headerMap = new ArrayMap<>();
        headerMap.put("X-HTTP-Method-Override", "PATCH");
        headerMap.put("Charset", "utf-8");
        headerMap.put("Connection", "keep-alive");
        headerMap.put("X-Platform", "Android");
        headerMap.put("X-request-from", "external");
        headerMap.forEach(builder::addHeader);
    }
}
